#pragma once
#include <iostream>
#include <string>
#include "InetAddr.hpp"
#include "Socket.hpp"
#include <jsoncpp/json/json.h>
#include <functional>
// 自定义网络计算器
using namespace SocketModule;
// client->serve
class Request
{
public:
    Request() {};
    Request(int x, int y, char oper)
        : _x(x),
          _y(y),
          _oper(oper) {};
    std::string Serialize()
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;

        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        if (reader.parse(in, root))
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
            return true;
        }
        return false;
    }
    ~Request() {};

    int X() { return _x; }
    int Y() { return _y; }
    int OPER() { return _oper; }

private:
    int _x;
    int _y;
    char _oper;
};

// serve->client
class Response
{
public:
    Response() {};
    Response(int resault, int code) {

    };
    std::string Serialize()
    {
        Json::Value root;
        root["resault"] = _resault;
        root["code"] = _code;

        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        if (reader.parse(in, root))
        {
            _resault = root["resault"].asInt();
            _code = root["code"].asInt();
            return true;
        }
        return false;
    }
    ~Response() {};

    void SetResault(int res) { _resault = res; }
    void SetCode(int code) { _code = code; }
    void ShowResault()
    {
        std::cout << "计算结果是： " << _resault << '[' << _code << ']' << std::endl;
    }

private:
    int _resault;
    int _code = 0; // 0:运算正常，1，2，3，4-》运算失败
};

const std::string sep = "/r/n";
using func_t = std::function<Response(Request &)>;

class Protocol
{
public:
    Protocol() {};
    // 初始化传业务处理的函数
    Protocol(func_t func) : _func(func)
    {
    }

    // 添加报文
    std::string Encode(std::string json_str)
    {
        std::string len = std::to_string(json_str.size());
        return len + sep + json_str + sep; // 应用层封装报头
    }
    // 解码报文
    bool Decode(std::string &buffer, std::string *package)
    {
        ssize_t pos = buffer.find(sep);
        if (pos == std::string::npos)
        {
            return false;
        };
        std::string package_len_str = buffer.substr(0, pos);
        int package_len_int = std::stoi(package_len_str);

        int target_int = package_len_str.size() + package_len_int + sep.size() * 2;
        if (buffer.size() < target_int)
        {
            return false;
        };

        *package = buffer.substr(pos + sep.size(), package_len_int);
        buffer.erase(0, target_int);
        return true;
    }

    // 客户层回调
    void GetRequest(std::shared_ptr<SocketModule::Socket> &socket, InetAddr &addr)
    {
        std::string message;
        while (true)
        {
            int n = socket->Recv(&message);
            if (n > 0)
            {
                std::string json_package;
                while (Decode(message, &json_package))
                {
                    std::cout << "message->" << message << std::endl;
                    // 得到了一个JSON串，反序列化
                    Request req;
                    bool ok = req.Deserialize(json_package);
                    if (!ok)
                        continue;
                    // 处理反系列化后的字符串
                    // 同样也是main里面需要lambda的初始化构造传入的函数
                    //业务层函数
                    Response resp = _func(req);
                    std::string json_str = resp.Serialize();
                    // 添加报文
                    std::string send_str = Encode(json_str);

                    socket->Send(send_str);
                }
            }
            else if (n == 0)
            {
                LOG(LogLevel::INFO) << "client:" << addr.StringAddr() << "Quit";
                break;
            }
            else
            {
                LOG(LogLevel::WARNING) << addr.StringAddr() << "error";
                break;
            }
            
        }
    };

    bool GetResponse(std::shared_ptr<Socket> &client, std::string &resp_str, Response *resp)
    {
        // 面向字节流
        while (true)
        {
            int n = client->Recv(&resp_str);
            if (n > 0)
            {
                std::string json_package;
                // bool ret = Decode(resp_str, &json_package);
                // // 读取字节流完整报文的关键
                // if (!ret)
                //     continue;
                while(Decode(resp_str, &json_package))
                {
                    resp->Deserialize(json_package);
                    // resp->ShowResault();
                }
                
                return true;
            }
            else if (n == 0)
            {
                std::cout << "serve quit!" << std::endl;
                return false;
            }
            else
            {
                std::cout << "recv error" << std::endl;
                return false;
            }
        }
    }
    // 客户端协议化数据
    std::string BuildRequestString(int x, int y, char oper)
    {
        Request req(x, y, oper);
        std::string json_req = req.Serialize();
        std::cout << "-------------json_str----------------" << std::endl;
        std::cout << json_req << std::endl;
        std::cout << "-------------------------------------" << std::endl;
        return Encode(json_req);
    }

private:
    func_t _func;
};